package com.gaussian.property.admin.module.biz.service;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.gaussian.property.admin.module.biz.vo.checktable.CheckTableExcelVo;
import com.gaussian.property.admin.module.biz.vo.checktable.CheckTableVo;
import com.gaussian.property.admin.module.biz.vo.checktable.PageQueryCheckTableRequest;
import com.gaussian.property.module.biz.entity.*;
import com.gaussian.property.module.biz.mapper.CheckTableMapper;
import com.gaussian.property.module.biz.service.ICheckCriteriaService;
import com.gaussian.property.module.biz.service.ICheckModuleService;
import com.gaussian.property.module.biz.service.ICheckStandardService;
import com.gaussian.property.module.biz.service.IProjectCheckTableService;
import com.gaussian.property.module.biz.service.impl.AbstractCheckTableServiceImpl;
import com.songqi.common.core.constant.Constants;
import com.songqi.common.core.exception.CustomException;
import com.songqi.common.core.utils.BeanCopyUtil;
import com.songqi.common.mybatis.core.query.LambdaQueryWrapperX;
import com.songqi.common.mybatis.core.util.MyBatisUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @description:
 * @author: songqi(13776346982)
 * @date: 2024/4/12 09:27
 */
@Service
public class CheckTableService extends AbstractCheckTableServiceImpl<CheckTableMapper, CheckTable> {



    @Resource
    private ICheckModuleService iCheckModuleService;
    @Resource
    private ICheckCriteriaService  iCheckCriteriaService;
    @Resource
    private ICheckStandardService iCheckStandardService;
    @Resource
    private IProjectCheckTableService iProjectCheckTableService;

    /**
     * 1到100之间，允许1或2位小数
     */
    private static final Pattern PATTERN1_100 = Pattern.compile("^(100(\\.0{1,2})?|([1-9]\\d?)(\\.\\d{1,2})?)$");

    /**
     * 0到100之间整数
     */
    private static final Pattern PATTERN0_100_INT = Pattern.compile("^(100|[1-9]?\\d)$");

    /**
     * 0到100之间，允许一位小数
     */
    private static final Pattern PATTERN0_100 = Pattern.compile("^100(\\.0)?$|^\\d{1,2}(\\.\\d)?$");


    public IPage<CheckTable> pageQueryCheckTable(PageQueryCheckTableRequest queryRequest) {
        IPage<CheckTable> iPage = MyBatisUtils.buildPage(queryRequest);
        LambdaQueryWrapperX<CheckTable> queryWrapper = new LambdaQueryWrapperX<CheckTable>()
                .likeIfPresent(CheckTable::getCheckName, queryRequest.getTableName())
                .likeIfPresent(CheckTable::getRemark, queryRequest.getRemark())
                .orderByDesc(CheckTable::getCreateTime);

        return super.page(iPage, queryWrapper);
    }

    /**
     * 新增稽核表
     * @param addCheckTable
     */
    @Transactional(rollbackFor = Exception.class)
    public void addCheckTable(CheckTableVo addCheckTable) {

        String checkName = addCheckTable.getCheckName();
        checkIsCheckNameRepeat(checkName);
        List<CheckTableVo.CheckModuleVo> checkModuleVoList = addCheckTable.getCheckModuleVoList();
        // 验证分值是否合规
        double sumModuleScore = validateScore(checkModuleVoList);
        // 保存
        CheckTable checkTable = new CheckTable();
        checkTable.setCheckName(checkName);
        checkTable.setRemark(addCheckTable.getRemark());
        checkTable.setScore(sumModuleScore);
        super.save(checkTable);
        String checkTableId = checkTable.getCheckTableId();
        saveCheckModuleCriteriaStandard(checkModuleVoList, checkTableId);
    }




    /**
     * 编辑稽核表
     * @param editCheckTable
     */
    @Transactional(rollbackFor = Exception.class)
    public void editCheckTable(CheckTableVo editCheckTable) {
        String checkTableId = editCheckTable.getCheckTableId();
        CheckTable checkTable = super.getById(checkTableId);
        if(checkTable == null){
            throw new CustomException("【参数错误】稽核表id不存在");
        }
        // 判断稽核表是否绑定启用的项目
        if(checkIsBindingEnableProject(checkTableId)){
            throw new CustomException("该稽核标准绑定了启用的项目，不能编辑。");
        }
        if(! checkTable.getCheckName().equals(editCheckTable.getCheckName())){
            checkIsCheckNameRepeat(editCheckTable.getCheckName());
        }
        List<CheckTableVo.CheckModuleVo> checkModuleVoList = editCheckTable.getCheckModuleVoList();
        // 验证分值是否合规
        double sumModuleScore = validateScore(checkModuleVoList);
        // 更新稽核表
        checkTable.setCheckName(editCheckTable.getCheckName());
        checkTable.setRemark(editCheckTable.getRemark());
        checkTable.setScore(sumModuleScore);
        super.updateById(checkTable);
        // 处理模块的新增、删除、修改的数据。并在模块中处理指标和标准的新增、删除、修改的数据
        dealEditCheckModuleVoList(checkTableId,checkModuleVoList);
    }




    /**
     * 删除稽核表
     * @param checkTableId
     */
    public void delCheckTable(String checkTableId) {
        // 判断稽核表是否绑定启用的项目
        if(checkIsBindingEnableProject(checkTableId)){
            throw new CustomException("该稽核标准绑定了启用的项目，不能删除。");
        };
        super.removeById(checkTableId);
    }

    public CheckTableVo viewDetail(String checkTableId) {
        CheckTable checkTable = getById(checkTableId);
        if(checkTable == null){
            throw new CustomException("【参数错误】稽核表id不存在");
        }
        CheckTableVo checkTableVo = BeanCopyUtil.copyProperties(checkTable, CheckTableVo.class);
        List<CheckModule> checkModules = queryCheckModuleList(checkTableId);
        if(CollectionUtil.isNotEmpty(checkModules)){
            checkTableVo.setCheckModuleVoList(BeanCopyUtil.copyList(checkModules, CheckTableVo.CheckModuleVo.class));
            for(CheckTableVo.CheckModuleVo checkModuleVo: checkTableVo.getCheckModuleVoList()){
                List<CheckCriteria> checkCriteriaList = queryCheckCriteriaList(checkModuleVo.getCheckModuleId());
                if(CollectionUtil.isNotEmpty(checkCriteriaList)){
                    checkModuleVo.setCheckCriteriaVoList(BeanCopyUtil.copyList(checkCriteriaList, CheckTableVo.CheckCriteriaVo.class));
                    for(CheckTableVo.CheckCriteriaVo checkCriteriaVo: checkModuleVo.getCheckCriteriaVoList()){
                        List<CheckStandard> checkStandards = queryCheckStandardList(checkCriteriaVo.getCheckCriteriaId());
                        if(CollectionUtil.isNotEmpty(checkStandards)){
                            checkCriteriaVo.setCheckStandardVoList(BeanCopyUtil.copyList(checkStandards, CheckTableVo.CheckStandardVo.class));
                        }
                    }
                }
            }
        }
        return checkTableVo;
    }


    /**
     * 导入稽核表
     * @param file
     */
    @Transactional(rollbackFor = Exception.class)
    public void importCheckTableExcel(MultipartFile file) {
        List<CheckTableExcelVo> excelRowList = null;
        try {
            excelRowList = ExcelImportUtil.importExcel(file.getInputStream(), CheckTableExcelVo.class, new ImportParams());
            if (CollectionUtil.isEmpty(excelRowList)) {
                throw new CustomException("Excel内容为空");
            }
        } catch (Exception e) {
            log.error("读取excel发生异常", e);
            throw new CustomException("读取excel发生异常。请重试");
        }
        String checkName = FileNameUtil.mainName(file.getOriginalFilename());
        checkIsCheckNameRepeat(checkName);
        Map<Integer, CheckTableExcelVo> rowMap = new HashMap<>(excelRowList.size());
        int i = 1;
        for (CheckTableExcelVo excelRow : excelRowList) {
            int excelRowNum = i + 1;
            // 将记录打上行号
            excelRow.setRowNo(i);
            rowMap.put(i, excelRow);
            if (StrUtil.isNotBlank(excelRow.getModuleName())) {
                excelRow.setModuleRowNo(i);
                if (StrUtil.isBlank(excelRow.getModuleScore())) {
                    throw new CustomException("第" + excelRowNum + "行记录模块分值必填");
                } else if (!isValidNumber(PATTERN0_100_INT, excelRow.getModuleScore())) {
                    throw new CustomException("第" + excelRowNum + "行记录模块分值只允许0-100");
                }
                String isAllowAttach = excelRow.getIsAllowAttach();
                if(StrUtil.isBlank(isAllowAttach)){
                    throw new CustomException("第" + excelRowNum + "行记录稽核附件必填");
                }else if(! ("必填".equals(isAllowAttach) || "非必填".equals(isAllowAttach))){
                     throw new CustomException("第" + excelRowNum + "行记录稽核附件只能“必填”或“非必填”");
                }
                String isAddScore = excelRow.getIsAllowAddScore();
                if(StrUtil.isBlank(isAddScore)){
                    throw new CustomException("第" + excelRowNum + "行记录是否加分必填");
                }else if(!("是".equals(isAddScore) || "否".equals(isAddScore))){
                    throw new CustomException("第" + excelRowNum + "行记录是否加分只能“是”或“否”");
                }
            } else {
                CheckTableExcelVo moduleRow = findUpperModuleRow(i, rowMap);
                if (moduleRow != null) {
                    excelRow.setModuleRowNo(moduleRow.getRowNo());
                } else {
                    throw new CustomException("第" + excelRowNum + "行记录未找到上级模块");
                }
            }

            if (StrUtil.isNotBlank(excelRow.getCriteriaName())) {
                excelRow.setCriteriaRowNo(i);
                if (StrUtil.isNotBlank(excelRow.getCriteriaScore())
                        && ! isValidNumber(PATTERN0_100, excelRow.getCriteriaScore())) {
                    throw new CustomException("第" + excelRowNum + "行记录指标分值只允许0-100");
                }
            } else {
                CheckTableExcelVo criteriaRow = findUpperCriteriaRow(i, rowMap);
                if (criteriaRow != null) {
                    excelRow.setCriteriaRowNo(criteriaRow.getRowNo());
                } else {
                    throw new CustomException("第" + excelRowNum + "行记录未找到上级指标");
                }
            }
            if (StrUtil.isNotBlank(excelRow.getStandardScore())
                    && !isValidNumber(PATTERN0_100, excelRow.getStandardScore())) {
                throw new CustomException("第" + excelRowNum + "行记录标准分值只允许0-100");
            }
            i++;
        }
        List<CheckTableVo.CheckModuleVo> checkModuleVoList = convert2CheckModuleVoList(excelRowList, rowMap);
        double sumModuleScore = validateScore(checkModuleVoList);
        // 保存
        CheckTable checkTable = new CheckTable();
        checkTable.setCheckName(checkName);
        checkTable.setScore(sumModuleScore);
        super.save(checkTable);
        String checkTableId = checkTable.getCheckTableId();
        saveCheckModuleCriteriaStandard(checkModuleVoList, checkTableId);

    }



    public static boolean isValidNumber(Pattern pattern, String number) {
        return pattern.matcher(number).matches();
    }


    /**
     * 判断稽核表名称是否重复
     * @param checkName
     */
    private void checkIsCheckNameRepeat(String checkName) {
        LambdaQueryWrapper<CheckTable> queryWrapper = new LambdaQueryWrapper<CheckTable>()
                .eq(CheckTable::getCheckName, checkName);
        if(super.count(queryWrapper) > 0){
            throw new CustomException("稽核标准名称已重复");
        }
    }

    /**
     * 判断稽核表是否绑定启用的项目
     * @param checkTableId
     */
    private boolean checkIsBindingEnableProject(String checkTableId) {
        LambdaQueryWrapper<ProjectCheckTable> queryWrapper = new LambdaQueryWrapper<ProjectCheckTable>()
                .eq(ProjectCheckTable::getStatus, Constants.ENABLE)
                .eq(ProjectCheckTable::getIsDelete, Constants.NO)
                .eq(ProjectCheckTable::getCheckTableId, checkTableId);
        return iProjectCheckTableService.count(queryWrapper) > 0;
    }


    private List<CheckTableVo.CheckModuleVo> convert2CheckModuleVoList(List<CheckTableExcelVo> excelRowList, Map<Integer, CheckTableExcelVo> rowMap) {
        // 转换
        List<CheckTableVo.CheckModuleVo> checkModuleVoList = new ArrayList<>();
        Map<Integer, List<CheckTableExcelVo>> moduleMap = excelRowList.stream()
                .collect(Collectors.groupingBy(CheckTableExcelVo::getModuleRowNo));
        // 默认TreeMap按Key排序。moduleMap的key是行号
        Map<Integer, List<CheckTableExcelVo>> moduleGroupMap = new TreeMap<>(moduleMap);
        int moduleSortNum = 1;
        int criteriaSortNum = 1;
        int standardSortNum = 1;
        for(Map.Entry<Integer, List<CheckTableExcelVo>> moduleEntry: moduleGroupMap.entrySet()){
            Integer moduleRowNo = moduleEntry.getKey();
            List<CheckTableExcelVo> checkModuleRowList = moduleEntry.getValue();
            checkModuleRowList.sort(Comparator.comparing(CheckTableExcelVo::getRowNo));
            CheckTableExcelVo moduleRow = rowMap.get(moduleRowNo);
            CheckTableVo.CheckModuleVo checkModuleVo = new CheckTableVo.CheckModuleVo();
            checkModuleVo.setSortNum(moduleSortNum);
            checkModuleVo.setModuleName(moduleRow.getModuleName());
            if(StrUtil.isNotBlank(moduleRow.getModuleScore())){
                checkModuleVo.setScore(Double.parseDouble(moduleRow.getModuleScore()));
            }
            checkModuleVo.setIsAllowAddScore(moduleRow.getIsAllowAddScore().equals("是") ? 1 : 0);
            checkModuleVo.setIsAllowAttach(moduleRow.getIsAllowAttach().equals("必填") ? 1 : 0);

            Map<Integer, List<CheckTableExcelVo>> criteriaMap = checkModuleRowList.stream().collect(Collectors.groupingBy(CheckTableExcelVo::getCriteriaRowNo));
            Map<Integer, List<CheckTableExcelVo>> criteriaGroupMap = new TreeMap<>(criteriaMap);
            List<CheckTableVo.CheckCriteriaVo> checkCriteriaVoList = new ArrayList<>();
            for(Map.Entry<Integer, List<CheckTableExcelVo>> criteriaEntry : criteriaGroupMap.entrySet()){
                Integer criteriaRowNo = criteriaEntry.getKey();
                List<CheckTableExcelVo> checkStandardRowList = criteriaEntry.getValue();
                CheckTableExcelVo criteriaRow = rowMap.get(criteriaRowNo);
                CheckTableVo.CheckCriteriaVo checkCriteriaVo = new CheckTableVo.CheckCriteriaVo();
                checkCriteriaVo.setSortNum(criteriaSortNum);
                checkCriteriaVo.setCriteriaName(criteriaRow.getCriteriaName());
                if(StrUtil.isNotBlank(criteriaRow.getCriteriaScore())){
                    checkCriteriaVo.setScore(Double.parseDouble(criteriaRow.getCriteriaScore()));
                }
                if(CollectionUtil.isNotEmpty(checkStandardRowList)){
                    List<CheckTableVo.CheckStandardVo> checkStandardVoList = new ArrayList<>();
                    for(CheckTableExcelVo checkStandardRow: checkStandardRowList){
                        CheckTableVo.CheckStandardVo checkStandardVo = new CheckTableVo.CheckStandardVo();
                        checkStandardVo.setSortNum(standardSortNum);
                        checkStandardVo.setStandardName(checkStandardRow.getStandardName());
                        checkStandardVo.setDeductionItem(checkStandardRow.getDeductionItem());
                        if(StrUtil.isNotBlank(checkStandardRow.getStandardScore())){
                            checkStandardVo.setScore(Double.parseDouble(checkStandardRow.getStandardScore()));
                        }
                        checkStandardVoList.add(checkStandardVo);
                        standardSortNum++;
                    }
                    checkCriteriaVo.setCheckStandardVoList(checkStandardVoList);
                }
                checkCriteriaVoList.add(checkCriteriaVo);
                criteriaSortNum++;
            }
            checkModuleVo.setCheckCriteriaVoList(checkCriteriaVoList);
            checkModuleVoList.add(checkModuleVo);
            moduleSortNum++;
        }
        return checkModuleVoList;
    }

    private CheckTableExcelVo findUpperCriteriaRow(int i, Map<Integer, CheckTableExcelVo> rowMap) {
        for(; i > 0; i--){
            CheckTableExcelVo excelRow = rowMap.get(i);
            if(StrUtil.isNotBlank(excelRow.getCriteriaName())){
                return excelRow;
            }
        }
        return null;
    }

    private CheckTableExcelVo findUpperModuleRow(int i, Map<Integer, CheckTableExcelVo> rowMap) {
        for(; i > 0; i--){
            CheckTableExcelVo excelRow = rowMap.get(i);
            if(StrUtil.isNotBlank(excelRow.getModuleName())){
                return excelRow;
            }
        }
        return null;
    }


    /**
     * 验证分值是否合规
     * @param checkModuleVoList
     */
    private double validateScore(List<CheckTableVo.CheckModuleVo> checkModuleVoList) {
        double sumModuleScore = 0;
        // 所有不允许加分的模块设置的分值和不能超过100
        double sumDeductionModuleScore = 0;
        if(CollectionUtil.isNotEmpty(checkModuleVoList)){
            for(CheckTableVo.CheckModuleVo checkModuleVo : checkModuleVoList){
                Double moduleScore = checkModuleVo.getScore();
                // 模块是否允许加分
                Integer isAllowAddScore = checkModuleVo.getIsAllowAddScore();
                // 模块设分的分值不能超过100
                if(Constants.NO == isAllowAddScore ){
                    sumDeductionModuleScore += moduleScore;
                }
                List<CheckTableVo.CheckCriteriaVo> checkCreteriaVoList = checkModuleVo.getCheckCriteriaVoList();
                if(CollectionUtil.isNotEmpty(checkCreteriaVoList)){
                    double sumCriteriaScore = 0;
                    for(CheckTableVo.CheckCriteriaVo checkCriteriaVo : checkCreteriaVoList){
                        Double criteriaScore = checkCriteriaVo.getScore();
                        List<CheckTableVo.CheckStandardVo> checkStandardVoList = checkCriteriaVo.getCheckStandardVoList();
                        if(CollectionUtil.isNotEmpty(checkStandardVoList)){
                            double sumStandardScore = 0;
                            for(CheckTableVo.CheckStandardVo checkStandardVo : checkStandardVoList){
                                Double standardScore = checkStandardVo.getScore();
                                if(standardScore != null && standardScore > 0){
                                    sumStandardScore += standardScore;
                                }
                                String standardName = checkStandardVo.getStandardName();
                                if(StrUtil.isBlank(standardName) ){
                                    throw new CustomException("标准作业名称必填");
                                }
                            }
                            if(criteriaScore !=null && criteriaScore > 0 && sumStandardScore > criteriaScore){
                                throw new CustomException("标准分值总和不能大于指标分值");
                            }
                        }
                        if(criteriaScore !=null && criteriaScore > 0 ){
                            sumCriteriaScore += criteriaScore;
                        }
                    }
                    if(moduleScore != null && moduleScore > 0 && sumCriteriaScore > moduleScore){
                        throw new CustomException("指标分值总和不能大于模块分值");
                    }
                }
                if(moduleScore != null && moduleScore > 0 ){
                    sumModuleScore += moduleScore;
                }
            }
        }
        if(sumDeductionModuleScore > 100){
            throw new CustomException("所有不允许加分的模块设置的分值和不能超过100");
        }
        return sumModuleScore;
    }

    /**
     * 处理模块的新增、删除、修改的数据。并在模块中处理指标和标准的新增、删除、修改的数据
     * @param checkModuleVoList
     * @param checkTableId
     */
    private void dealEditCheckModuleVoList(String checkTableId, List<CheckTableVo.CheckModuleVo> checkModuleVoList) {
        if(CollectionUtil.isNotEmpty(checkModuleVoList)) {
            // 稽核表中已有的模块id列表
            List<String> checkModuleIdListInCheckTable = queryCheckModuleIds(checkTableId);
            List<CheckModule> newCheckModuleList = new ArrayList<>();
            List<CheckModule> updatedCheckModuleList = new ArrayList<>();
            List<String> removedCheckModuleIdList = new ArrayList<>(checkModuleIdListInCheckTable);
            for (CheckTableVo.CheckModuleVo checkModuleVo : checkModuleVoList) {
                String checkModuleId = checkModuleVo.getCheckModuleId();
                // 前端没有传checkModuleId的，判定为新增的
                if (StrUtil.isBlank(checkModuleId)){
                    checkModuleId = IdWorker.getIdStr();
                    CheckModule checkModule = BeanCopyUtil.copyProperties(checkModuleVo, CheckModule.class);
                    checkModule.setCheckModuleId(checkModuleId);
                    checkModule.setCheckTableId(checkTableId);
                    newCheckModuleList.add(checkModule);
                }
                // 前端传checkModuleId在稽核表的moduleId中，判定为更新
                else if(checkModuleIdListInCheckTable.contains(checkModuleId)){
                    CheckModule checkModule = BeanCopyUtil.copyProperties(checkModuleVo, CheckModule.class);
                    checkModule.setCheckTableId(checkTableId);
                    updatedCheckModuleList.add(checkModule);
                }else {
                    throw new CustomException("【参数错误】模块id不存在");
                }
                // 模块下的标准列表
                List<CheckTableVo.CheckCriteriaVo> checkCriteriaVoList = checkModuleVo.getCheckCriteriaVoList();
                //  处理标准的新增、删除、修改的数据。并在标准中处理标准的新增、删除、修改的数据
                dealEditCheckCriteriaVoList(checkTableId, checkModuleId, checkCriteriaVoList);
            }
            // 找出删除的模块id
            List<String> updatedCheckModuleIdList = updatedCheckModuleList.stream().map(CheckModule::getCheckModuleId).collect(Collectors.toList());
            removedCheckModuleIdList.removeAll(updatedCheckModuleIdList);
            //保存新的模块
            iCheckModuleService.saveBatch(newCheckModuleList);
            //更新新已有模块
            iCheckModuleService.updateBatchById(updatedCheckModuleList);
            // 逻辑删除稽核指标、标准、模块
            if(CollectionUtil.isNotEmpty(removedCheckModuleIdList)){
                LambdaQueryWrapper<CheckStandard> checkStandardQueryWrapper = new LambdaQueryWrapper<CheckStandard>()
                        .in(CheckStandard::getCheckModuleId, removedCheckModuleIdList);
                iCheckStandardService.remove(checkStandardQueryWrapper);
                LambdaQueryWrapper<CheckCriteria> checkCriteriaQueryWrapper = new LambdaQueryWrapper<CheckCriteria>()
                        .in(CheckCriteria::getCheckModuleId, removedCheckModuleIdList);
                iCheckCriteriaService.remove(checkCriteriaQueryWrapper);
                iCheckModuleService.removeBatchByIds(removedCheckModuleIdList);
            }
        }
    }


    /**
     * 处理前端送过来的编辑标准参数
     * @param checkTableId
     * @param checkModuleId
     * @param checkCriteriaVoList
     */
    private void dealEditCheckCriteriaVoList(String checkTableId, String checkModuleId, List<CheckTableVo.CheckCriteriaVo> checkCriteriaVoList) {
        if(CollectionUtil.isNotEmpty(checkCriteriaVoList)){
            // 模块下已有的标准id列表。如果为空，1：当前模块是新增的。2：当前模块原来就没有标准。
            // 两种情况的最终结果是：前端传过来的checkCriteriaId一定是空的。
            List<String> checkCriteriaIdListInModule = queryCheckCriteriaIds(checkModuleId);
            List<CheckCriteria> newCheckCriteriaList = new ArrayList<>();
            List<CheckCriteria> updatedCheckCriteriaList = new ArrayList<>();
            List<String> removedCheckCriteriaIdList = new ArrayList<>(checkCriteriaIdListInModule);
            for(CheckTableVo.CheckCriteriaVo checkCriteriaVo : checkCriteriaVoList){
                String checkCriteriaId = checkCriteriaVo.getCheckCriteriaId();
                if(StrUtil.isBlank(checkCriteriaId)){
                    checkCriteriaId = IdWorker.getIdStr();
                    CheckCriteria checkCriteria = BeanCopyUtil.copyProperties(checkCriteriaVo, CheckCriteria.class);
                    checkCriteria.setCheckCriteriaId(checkCriteriaId);
                    checkCriteria.setCheckModuleId(checkModuleId);
                    checkCriteria.setCheckTableId(checkTableId);
                    newCheckCriteriaList.add(checkCriteria);
                } else if(checkCriteriaIdListInModule.contains(checkCriteriaId)){
                    CheckCriteria checkCriteria = BeanCopyUtil.copyProperties(checkCriteriaVo, CheckCriteria.class);
                    checkCriteria.setCheckTableId(checkTableId);
                    checkCriteria.setCheckModuleId(checkModuleId);
                    updatedCheckCriteriaList.add(checkCriteria);
                }else {
                    throw new CustomException("【参数错误】标准id不存在");
                }

                // 处理前端传过来的编辑标准参数
                List<CheckTableVo.CheckStandardVo> checkStandardVoList = checkCriteriaVo.getCheckStandardVoList();
                dealEditCheckStandardVoList(checkTableId, checkModuleId, checkCriteriaId, checkStandardVoList);

            }

            //找出删除的标准id
            List<String> updatedCheckCriteriaIdList = updatedCheckCriteriaList.stream().map(CheckCriteria::getCheckCriteriaId).collect(Collectors.toList());
            removedCheckCriteriaIdList.removeAll(updatedCheckCriteriaIdList);
            // 保存新的标准
            iCheckCriteriaService.saveBatch(newCheckCriteriaList);
            // 更新已有标准
            iCheckCriteriaService.updateBatchById(updatedCheckCriteriaList);
            // 逻辑删除稽核指标、标准
            if(CollectionUtil.isNotEmpty(removedCheckCriteriaIdList)){
                LambdaQueryWrapper<CheckStandard> checkStandardQueryWrapper = new LambdaQueryWrapper<CheckStandard>()
                        .in(CheckStandard::getCheckCriteriaId, removedCheckCriteriaIdList);
                iCheckStandardService.remove(checkStandardQueryWrapper);
                iCheckCriteriaService.removeBatchByIds(removedCheckCriteriaIdList);
            }
        }
    }

    private void dealEditCheckStandardVoList(String checkTableId, String checkModuleId, String checkCriteriaId, List<CheckTableVo.CheckStandardVo> checkStandardVoList) {
        if(CollectionUtil.isNotEmpty(checkStandardVoList)){
            List<String> checkStandardIdListInCriteria = queryCheckStandardIds(checkCriteriaId);
            List<CheckStandard> newCheckStandardList = new ArrayList<>();
            List<CheckStandard> updatedCheckStandardList = new ArrayList<>();
            List<String> removedCheckStandardIdList = new ArrayList<>(checkStandardIdListInCriteria);
            for(CheckTableVo.CheckStandardVo checkStandardVo : checkStandardVoList){
                String checkStandardId = checkStandardVo.getCheckStandardId();
                if(StrUtil.isBlank(checkStandardId)){
                    CheckStandard checkStandard = BeanCopyUtil.copyProperties(checkStandardVo, CheckStandard.class);
                    checkStandard.setCheckCriteriaId(checkCriteriaId);
                    checkStandard.setCheckModuleId(checkModuleId);
                    checkStandard.setCheckTableId(checkTableId);
                    newCheckStandardList.add(checkStandard);
                }else if(checkStandardIdListInCriteria.contains(checkStandardId)){
                    CheckStandard checkStandard = BeanCopyUtil.copyProperties(checkStandardVo, CheckStandard.class);
                    checkStandard.setCheckTableId(checkTableId);
                    checkStandard.setCheckModuleId(checkModuleId);
                    checkStandard.setCheckCriteriaId(checkCriteriaId);
                    updatedCheckStandardList.add(checkStandard);
                }else {
                    throw new CustomException("【参数错误】指标id不存在");
                }
            }
            //找出删除的标准id
            List<String> updatedCheckStandardIdList = updatedCheckStandardList.stream().map(CheckStandard::getCheckStandardId).collect(Collectors.toList());
            removedCheckStandardIdList.removeAll(updatedCheckStandardIdList);
            iCheckStandardService.saveBatch(newCheckStandardList);
            iCheckStandardService.updateBatchById(updatedCheckStandardList);
            iCheckStandardService.removeBatchByIds(removedCheckStandardIdList);
        }
    }

    private List<String> queryCheckStandardIds(String checkCriteriaId) {
        List<CheckStandard> checkStandardList = queryCheckStandardList(checkCriteriaId);
        return checkStandardList.stream().map(CheckStandard::getCheckStandardId).collect(Collectors.toList());
    }

    private List<CheckStandard> queryCheckStandardList(String checkCriteriaId) {
        LambdaQueryWrapper<CheckStandard> queryWrapper = new LambdaQueryWrapper<CheckStandard>()
                .eq(CheckStandard::getCheckCriteriaId, checkCriteriaId);
        return iCheckStandardService.list(queryWrapper);
    }


    private List<String> queryCheckCriteriaIds(String checkModuleId) {
        List<CheckCriteria> checkCriteriaList = queryCheckCriteriaList(checkModuleId);
        return checkCriteriaList.stream().map(CheckCriteria::getCheckCriteriaId).collect(Collectors.toList());
    }

    private List<CheckCriteria> queryCheckCriteriaList(String checkModuleId) {
        LambdaQueryWrapper<CheckCriteria> queryWrapper = new LambdaQueryWrapper<CheckCriteria>()
                .eq(CheckCriteria::getCheckModuleId, checkModuleId);
        return iCheckCriteriaService.list(queryWrapper);
    }




    /**
     * 根据稽核表id查询表中的所有模块id
     * @param checkTableId
     * @return
     */
    private List<String> queryCheckModuleIds(String checkTableId) {
        List<CheckModule> checkModules = queryCheckModuleList(checkTableId);
        return checkModules.stream().map(CheckModule::getCheckModuleId).collect(Collectors.toList());
    }

    /**
     * 根据稽核表id查询表中的所有模块
     * @param checkTableId
     * @return
     */
    private List<CheckModule> queryCheckModuleList(String checkTableId) {
        LambdaQueryWrapper<CheckModule> queryWrapper = new LambdaQueryWrapper<CheckModule>()
                .eq(CheckModule::getCheckTableId, checkTableId);
        return iCheckModuleService.list(queryWrapper);
    }




    /**
     * 保存稽核模块、指标、标准
     * @param checkModuleVoList
     * @param checkTableId
     */
    private void saveCheckModuleCriteriaStandard(List<CheckTableVo.CheckModuleVo> checkModuleVoList, String checkTableId) {
        if(CollectionUtil.isNotEmpty(checkModuleVoList)){
            List<CheckModule> checkModuleList = new ArrayList<>();
            for (CheckTableVo.CheckModuleVo checkModuleVo : checkModuleVoList) {
                String checkModuleId = IdWorker.getIdStr();
                CheckModule checkModule = BeanCopyUtil.copyProperties(checkModuleVo, CheckModule.class);
                checkModule.setCheckModuleId(checkModuleId);
                checkModule.setCheckTableId(checkTableId);
                checkModuleList.add(checkModule);

                if(CollectionUtil.isNotEmpty(checkModuleVo.getCheckCriteriaVoList())){
                    List<CheckCriteria> checkCriteriaList = new ArrayList<>();
                    for(CheckTableVo.CheckCriteriaVo checkCriteriaVo : checkModuleVo.getCheckCriteriaVoList()){
                        String checkCriteriaId = IdWorker.getIdStr();
                        CheckCriteria checkCriteria = BeanCopyUtil.copyProperties(checkCriteriaVo, CheckCriteria.class);
                        checkCriteria.setCheckCriteriaId(checkCriteriaId);
                        checkCriteria.setCheckModuleId(checkModuleId);
                        checkCriteria.setCheckTableId(checkTableId);
                        checkCriteriaList.add(checkCriteria);
                        if (CollectionUtil.isNotEmpty(checkCriteriaVo.getCheckStandardVoList())){
                            List<CheckStandard> checkStandardList = new ArrayList<>();
                            for (CheckTableVo.CheckStandardVo  checkStandardVo: checkCriteriaVo.getCheckStandardVoList()){
                                CheckStandard checkStandard = BeanCopyUtil.copyProperties(checkStandardVo, CheckStandard.class);
                                checkStandard.setCheckCriteriaId(checkCriteriaId);
                                checkStandard.setCheckModuleId(checkModuleId);
                                checkStandard.setCheckTableId(checkTableId);
                                checkStandardList.add(checkStandard);
                            }
                            iCheckStandardService.saveBatch(checkStandardList);
                        }
                    }
                    iCheckCriteriaService.saveBatch(checkCriteriaList);
                }
            }
            iCheckModuleService.saveBatch(checkModuleList);
        }
    }

    /**
     * 逻辑删除稽核模块、指标、标准
     * @param checkTableId
     */
    private void logicDeleteCheckModuleCriteriaStandard(String checkTableId) {
        LambdaQueryWrapper<CheckStandard> checkStandardQueryWrapper = new LambdaQueryWrapper<CheckStandard>()
                .eq(CheckStandard::getCheckTableId, checkTableId);
        iCheckStandardService.remove(checkStandardQueryWrapper);
        LambdaQueryWrapper<CheckCriteria> checkCriteriaQueryWrapper = new LambdaQueryWrapper<CheckCriteria>()
                .eq(CheckCriteria::getCheckTableId, checkTableId);
        iCheckCriteriaService.remove(checkCriteriaQueryWrapper);
        LambdaQueryWrapper<CheckModule> checkModuleQueryWrapper = new LambdaQueryWrapper<CheckModule>()
                .eq(CheckModule::getCheckTableId, checkTableId);
        iCheckModuleService.remove(checkModuleQueryWrapper);
    }



}
